package com.engine.qz.util;

import com.engine.kq.biz.KQExitRulesBiz;
import com.engine.kq.biz.KQLeaveRulesComInfo;
import com.engine.kq.biz.KQOvertimeRulesBiz;
import com.engine.kq.biz.KQTravelRulesBiz;
import com.engine.kq.biz.KQUnitBiz;
import com.engine.kq.biz.KQWorkTime;
import com.engine.kq.entity.WorkTimeEntity;
import com.engine.kq.enums.KqSplitFlowTypeEnum;
import com.engine.kq.util.KQDurationCalculatorUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import weaver.conn.RecordSet;
import weaver.formmode.setup.ModeRightInfo;
import weaver.general.BaseBean;
import weaver.general.Util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/**
 * @author zmnj516773695
 * @date 2024/08/12
 * @description
 **/
public class QzUtil {

    BaseBean bb = new BaseBean();

    private static DecimalFormat df = new DecimalFormat("0.00");

    private DecimalFormatSymbols symbols = new DecimalFormatSymbols();

    SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");

    SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm:ss");

    /**
     * 根据开始日期和结束日期，计算出之间的所有日期
     * @params startDate 指定日期
     * @params endDate 结束日期
     */
    public List<String> getAllDates(String startDate, String endDate) {
        List<String> result = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        LocalDate start = LocalDate.parse(startDate, formatter);
        LocalDate end = LocalDate.parse(endDate, formatter);

        while (!start.isAfter(end)) {
            result.add(start.format(formatter));
            start = start.plusDays(1);
        }

        return result;
    }

    // 获取存在请假或者出差或者公出的人员及日期
    public Set<String> getHrmRqSet(String startDate, String endDate) {
        RecordSet rs = new RecordSet();
        Set<String> existSet = new HashSet<>();
        Map<String, Double> xjMap = new HashMap<>();
        String sql = " select resourceid, newleavetype, durationrule, sum(duration) as val,belongdate from hrmresource a, "+ KqSplitFlowTypeEnum.LEAVEBACK.getTablename()+" b "+
                " where a.id = b.resourceid and belongdate >='"+startDate+"' and belongdate <='"+endDate+"' " +
                " group by resourceid, newleavetype, durationrule,belongdate ";
        rs.execute(sql);
        while (rs.next()) {
            String resourceid = rs.getString("resourceid");
            String belongdate = rs.getString("belongdate");
            double value = rs.getDouble("val")<0?0:rs.getDouble("val");
            if (value > 0) {
                xjMap.put(resourceid + "|" + belongdate, value);
            }
        }

        sql = " select resourceid, newleavetype, durationrule, sum(duration) as val,belongdate from hrmresource a, "+ KqSplitFlowTypeEnum.LEAVE.getTablename()+" b "+
                " where a.id = b.resourceid and belongdate >='"+startDate+"' and belongdate <='"+endDate+"' " +
                " group by resourceid, newleavetype, durationrule,belongdate ";
        rs.execute(sql);
        while (rs.next()) {
            String resourceid = rs.getString("resourceid");
            String belongdate = rs.getString("belongdate");
            double value = rs.getDouble("val")<0?0:rs.getDouble("val");
            if (value > 0) {
                if (CollectionUtils.isEmpty(xjMap)) {
                    existSet.add(resourceid + "|" + belongdate);
                } else {
                    Double xjDouble = xjMap.get(resourceid + "|" + belongdate);
                    if (xjDouble == null || value > xjDouble) {
                        existSet.add(resourceid + "|" + belongdate);
                    }
                }
            }
        }
        sql = " select resourceid, durationrule, sum(duration) as val,belongdate from hrmresource a, " + KqSplitFlowTypeEnum.EVECTION.getTablename()+" b "+
                " where a.id = b.resourceid and (b.status is null or b.status<>1) and belongdate >='"+startDate+"' and belongdate <='"+endDate+"' "+
                " group by resourceid, durationrule,belongdate ";
        rs.execute(sql);
        while (rs.next()) {
            String resourceid = rs.getString("resourceid");
            String belongdate = rs.getString("belongdate");
            double value = rs.getDouble("val")<0?0:rs.getDouble("val");
            if (value > 0) {
                existSet.add(resourceid + "|" + belongdate);
            }
        }
        sql = " select resourceid, durationrule, sum(duration) as val,belongdate from hrmresource a, " + KqSplitFlowTypeEnum.OUT.getTablename()+" b "+
                " where a.id = b.resourceid and (b.status is null or b.status<>1) and belongdate >='"+startDate+"' and belongdate <='"+endDate+"' "+
                " group by resourceid, durationrule,belongdate ";
        rs.execute(sql);
        while (rs.next()) {
            String resourceid = rs.getString("resourceid");
            String belongdate = rs.getString("belongdate");
            double value = rs.getDouble("val")<0?0:rs.getDouble("val");
            if (value > 0) {
                existSet.add(resourceid + "|" + belongdate);
            }
        }
        return existSet;
    }

    public void handleCQData(String userId, String kqDate, List<String> xxShiftList, Set<String> existSet, Map<String, String> lzMap, Map<String, String> statusMap) {
        BaseBean baseBean = new BaseBean();
        baseBean.writeLog("handleCQData start:" + userId + "、" + kqDate);
        RecordSet rs1 = new RecordSet();
        try {
            // 实际应出勤
            String sjmustcq = "0";
            // 实际已出勤
            String sjalreadycq = "0.0";
            double sjycqss = 0.00;

            boolean isOverLz = false;
            String lzrq = lzMap.get(userId);
            baseBean.writeLog("handleCQData lzrq:" + userId + "、" + lzrq);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            if (StringUtils.isNotEmpty(lzrq)) {
                LocalDate lzrqLd = LocalDate.parse(lzrq, formatter);
                LocalDate kqDateLd = LocalDate.parse(kqDate, formatter);
                if (!kqDateLd.isBefore(lzrqLd)) {
                    isOverLz = true;
                }
            }

            String statusT = "0";
            if ((!CollectionUtils.isEmpty(statusMap)) && statusMap.containsKey(userId)) {
                statusT = statusMap.get(userId);
            }
            if (StringUtils.isEmpty(statusT)) {
                statusT = "0";
            }

            boolean statusLz = false;
            if (StringUtils.isNotEmpty(statusT) && new BigDecimal(statusT).compareTo(new BigDecimal("5")) == 0) {
                statusLz = true;
            }

            if ((!isOverLz) || (!statusLz)) {
                // 判断是否休息班
                boolean isXxb = false;
                // 获取当天班次
                KQWorkTime kqWorkTime = new KQWorkTime();

                WorkTimeEntity workTime = kqWorkTime.getWorkTime(userId, kqDate);
                String bc = workTime.getSerialId();
                baseBean.writeLog("handleCQData bc:" + userId + "、" + bc);
                if (StringUtils.isEmpty(bc) || new BigDecimal(bc).compareTo(BigDecimal.ZERO) <= 0) {
                    return;
                }
                if ((!CollectionUtils.isEmpty(xxShiftList)) && xxShiftList.contains(bc)) {
                    isXxb = true;
                }
                baseBean.writeLog("handleCQData isXxb:" + isXxb);

                // 获取加班时长
                Map<String, Object> dailyFlowOverTimeData = getDailyFlowOverTimeDataAllowance(userId, kqDate);
                double workingDayOvertime_4leave = Util.getDoubleValue(Util.null2String(dailyFlowOverTimeData.get(userId + "|" + kqDate + "|workingDayOvertime_4leave")));
                workingDayOvertime_4leave = workingDayOvertime_4leave < 0 ? 0 : workingDayOvertime_4leave;
                double restDayOvertime_4leave = Util.getDoubleValue(Util.null2String(dailyFlowOverTimeData.get(userId + "|" + kqDate + "|restDayOvertime_4leave")));
                restDayOvertime_4leave = restDayOvertime_4leave < 0 ? 0 : restDayOvertime_4leave;
                double holidayOvertime_4leave = Util.getDoubleValue(Util.null2String(dailyFlowOverTimeData.get(userId + "|" + kqDate + "|holidayOvertime_4leave")));
                holidayOvertime_4leave = holidayOvertime_4leave < 0 ? 0 : holidayOvertime_4leave;

                double workingDayOvertime_nonleave = Util.getDoubleValue(Util.null2String(dailyFlowOverTimeData.get(userId + "|" + kqDate + "|workingDayOvertime_nonleave")));
                workingDayOvertime_nonleave = workingDayOvertime_nonleave < 0 ? 0 : workingDayOvertime_nonleave;
                double restDayOvertime_nonleave = Util.getDoubleValue(Util.null2String(dailyFlowOverTimeData.get(userId + "|" + kqDate + "|restDayOvertime_nonleave")));
                restDayOvertime_nonleave = restDayOvertime_nonleave < 0 ? 0 : restDayOvertime_nonleave;
                double holidayOvertime_nonleave = Util.getDoubleValue(Util.null2String(dailyFlowOverTimeData.get(userId + "|" + kqDate + "|holidayOvertime_nonleave")));
                holidayOvertime_nonleave = holidayOvertime_nonleave < 0 ? 0 : holidayOvertime_nonleave;

                double temp = workingDayOvertime_4leave + restDayOvertime_4leave + holidayOvertime_4leave +
                        workingDayOvertime_nonleave + restDayOvertime_nonleave + holidayOvertime_nonleave;

                sjycqss = sjycqss + (temp / 60);

                //先获取到实际打卡时长
                double signmins = 0.00;
                String acqAttenSql = " select resourceid, attendancemins, kqdate,signmins from kq_format_total where resourceid = " + userId + " and kqdate = '" + kqDate + "'";
                rs1.executeQuery(acqAttenSql);
                if (rs1.next()) {
                    signmins = Util.getDoubleValue(Util.null2String(rs1.getString("signmins")));
                    if (signmins < 0) {
                        signmins = 0.00;
                    }
                }

                sjycqss = sjycqss + (signmins / 60);

                if (isXxb) {
                    // 休息班：实际应出勤为0；实际已出勤=加班总时长
                    sjalreadycq = new BigDecimal(Double.toString(temp)).divide(new BigDecimal("60"), 2, RoundingMode.HALF_UP).toString();
                } else {
                    if (CollectionUtils.isEmpty(existSet) || !existSet.contains(userId + "|" + kqDate)) {
                        sjmustcq = "1";
                        if (signmins >= 0.00) {
                            sjalreadycq = new BigDecimal(Double.toString(signmins)).divide(new BigDecimal("60"), 2, RoundingMode.HALF_UP).toString();
                        }
                    }
                }

                KQLeaveRulesComInfo kqLeaveRulesComInfo = new KQLeaveRulesComInfo();

                String sql = " select resourceid, newleavetype, durationrule, sum(duration) as val,belongdate from hrmresource a, " + KqSplitFlowTypeEnum.LEAVE.getTablename() + " b " +
                        " where a.id = b.resourceid and belongdate >='" + kqDate + "' and belongdate <='" + kqDate + "' and b.resourceid = " + userId +
                        " group by resourceid, newleavetype, durationrule,belongdate ";
                rs1.execute(sql);
                while (rs1.next()) {
                    String resourceid = rs1.getString("resourceid");
                    String belongdate = rs1.getString("belongdate");
                    String newleavetype = rs1.getString("newleavetype");
                    String durationrule = rs1.getString("durationrule");
                    double value = rs1.getDouble("val") < 0 ? 0 : rs1.getDouble("val");

                    double proportion = Util.getDoubleValue(kqLeaveRulesComInfo.getProportion(newleavetype));
                    if (KQUnitBiz.isLeaveHour(newleavetype, kqLeaveRulesComInfo)) {//按小时
                        if (!KQUnitBiz.isLeaveHour(durationrule)) {
                            if (proportion > 0) value = value * proportion;
                        }
                    } else {//按天
                        if (KQUnitBiz.isLeaveHour(durationrule)) {
                            if (proportion > 0) value = value / proportion;
                        } else {
                            if (proportion > 0) value = value * proportion;
                        }
                    }
                    sjycqss = sjycqss + value;
                }

                sql = " select resourceid, newleavetype, durationrule, sum(duration) as val,belongdate from hrmresource a, " + KqSplitFlowTypeEnum.LEAVEBACK.getTablename() + " b " +
                        " where a.id = b.resourceid and belongdate >='" + kqDate + "' and belongdate <='" + kqDate + "' and b.resourceid =" + userId +
                        " group by resourceid, newleavetype, durationrule,belongdate ";
                rs1.execute(sql);
                while (rs1.next()) {
                    String resourceid = rs1.getString("resourceid");
                    String belongdate = rs1.getString("belongdate");
                    String newleavetype = rs1.getString("newleavetype");
                    String durationrule = rs1.getString("durationrule");
                    double value = rs1.getDouble("val") < 0 ? 0 : rs1.getDouble("val");

                    double proportion = Util.getDoubleValue(kqLeaveRulesComInfo.getProportion(newleavetype));
                    if (KQUnitBiz.isLeaveHour(newleavetype, kqLeaveRulesComInfo)) {//按小时
                        if (!KQUnitBiz.isLeaveHour(durationrule)) {
                            if (proportion > 0) value = value * proportion;
                        }
                    } else {//按天
                        if (KQUnitBiz.isLeaveHour(durationrule)) {
                            if (proportion > 0) value = value / proportion;
                        } else {
                            if (proportion > 0) value = value * proportion;
                        }
                    }
                    sjycqss = sjycqss - value;
                }

                String[] tables = new String[]{KqSplitFlowTypeEnum.EVECTION.getTablename(),//出差
                        KqSplitFlowTypeEnum.OUT.getTablename()};//公出
                for (String table : tables) {
                    sql = " select resourceid, durationrule, sum(duration) as val,belongdate from hrmresource a, " + table + " b " +
                            " where a.id = b.resourceid and (b.status is null or b.status<>1) and belongdate >='" + kqDate
                            + "' and belongdate <='" + kqDate + "' and b.resourceid = " + userId +
                            " group by resourceid, durationrule,belongdate ";
                    rs1.execute(sql);
                    while (rs1.next()) {
                        String resourceid = rs1.getString("resourceid");
                        String belongdate = rs1.getString("belongdate");
                        double value = rs1.getDouble("val");
                        String durationrule = rs1.getString("durationrule");

                        String minimumUnit = "";//单位类型
                        double proportion = 0.00;//换算关系
                        if (KqSplitFlowTypeEnum.EVECTION.getTablename().equals(table)) {
                            minimumUnit = KQTravelRulesBiz.getMinimumUnit();//单位类型
                            proportion = Util.getDoubleValue(KQTravelRulesBiz.getHoursToDay());//换算关系
                        } else if (KqSplitFlowTypeEnum.OUT.getTablename().equals(table)) {
                            minimumUnit = KQExitRulesBiz.getMinimumUnit();//单位类型
                            proportion = Util.getDoubleValue(KQExitRulesBiz.getHoursToDay());//换算关系
                        }

                        if (KQUnitBiz.isLeaveHour(minimumUnit)) {//按小时
                            if (!KQUnitBiz.isLeaveHour(durationrule)) {
                                if (proportion > 0) value = value * proportion;
                            }
                        } else {//按天
                            if (KQUnitBiz.isLeaveHour(durationrule)) {
                                if (proportion > 0) value = value / proportion;
                            } else {
                                if (proportion > 0) value = value * proportion;
                            }
                        }

                        // 出差和公出时长最多统计12小时
                        if (value > 12) {
                            value = 12;
                        }

                        sjycqss = sjycqss + value;
                    }
                }
            }

            String modeId = rs1.getPropValue("qz_zm_prop", "kqsjcqjsgl_modeid");
            String cusId = rs1.getPropValue("qz_zm_prop", "kqsjcqjsgl_cusid");
            baseBean.writeLog("sjycqts、sjycqss、sjycqss:" + sjmustcq + "、" + sjalreadycq + "、" + sjycqss);
            RecordSet rs2 = new RecordSet();
            rs1.executeQuery("select id from uf_kqsjcqjsglb where xm = ? and rq = ?", userId, kqDate);
            if (rs1.next()) {
                int dataId = rs1.getInt("id");
                rs2.executeUpdate("update uf_kqsjcqjsglb set sjycqts = ?, sjycqss = ?, sjdksc = ? where id = ?", sjmustcq, sjalreadycq, sjycqss, dataId);
                // 权限重构
                ModeRightInfo ModeRightInfo = new ModeRightInfo();
                ModeRightInfo.setNewRight(true);
                ModeRightInfo.editModeDataShare(1, Integer.parseInt(modeId), dataId);
            } else {
                if (isOverLz && statusLz) {
                    baseBean.writeLog("over lz, don`t need insert:" + userId + "、" + kqDate);
                    return;
                }
                String uuidT = UUID.randomUUID().toString();
                String nowDate = sdfDate.format(new Date());
                String nowTime = sdfTime.format(new Date());
                rs2.executeUpdate("INSERT INTO uf_kqsjcqjsglb (xm, rq, sjycqts, sjycqss, sjdksc, formmodeid, MODEUUID, modedatacreater, " +
                                "modedatacreatertype, modedatacreatedate, modedatacreatetime) VALUES (?,?,?,?,?,?,?,?,?,?,?)", userId, kqDate,
                        sjmustcq, sjalreadycq, sjycqss, modeId, uuidT, "1", "0", nowDate, nowTime);
                rs2.executeQuery("select id from uf_kqsjcqjsglb where MODEUUID = ?", uuidT);
                if (rs2.next()) {
                    int idT = rs2.getInt("id");
                    // 权限重构
                    ModeRightInfo ModeRightInfo = new ModeRightInfo();
                    ModeRightInfo.setNewRight(true);
                    ModeRightInfo.editModeDataShare(1, Integer.parseInt(modeId), idT);
                }
            }
        } catch (Exception e) {
            baseBean.writeLog("handleCQData error:" + e);
        }
    }

    public Map<String,Object> getDailyFlowOverTimeDataAllowance(String userId, String kqDate){
        BaseBean bb = new BaseBean();
        Map<String,Object> datas = new HashMap<>();;
        RecordSet rs = new RecordSet();
        String sql = "";
        String sqlWhere = " ";
        String valueRes = "";
        try{
            if(userId.length()>0){
                sqlWhere +=" and a.id in("+userId+") ";
            }
            KQOvertimeRulesBiz kqOvertimeRulesBiz = new KQOvertimeRulesBiz();
            int uintType = kqOvertimeRulesBiz.getMinimumUnit();//当前加班单位
            double hoursToDay = kqOvertimeRulesBiz.getHoursToDay();//当前天跟小时计算关系

            String valueField = "";
            if(uintType==3 || uintType== 5 || uintType== 6){//按小时计算
                valueField = "sum( case when durationrule='3' then duration else duration*"+hoursToDay+" end) as val";
            }else{//按天计算
                valueField = "sum( case when durationrule='3' then duration/"+hoursToDay+" else duration  end) as val";
            }

            sql = " select resourceid,changeType,belongdate,paidLeaveEnable, sum(cast(duration_min as decimal(18,4))) as val "+
                    " from hrmresource a, kq_flow_overtime b "+
                    " where a.id = b.resourceid and belongdate >='"+kqDate+"' and belongdate <='"+kqDate+"' " +sqlWhere+
                    " group by resourceid,changeType,paidLeaveEnable,belongdate ";
            rs.execute(sql);
            while (rs.next()) {
                String resourceid = rs.getString("resourceid");
                String belongdate = rs.getString("belongdate");
                String paidLeaveEnable = rs.getString("paidLeaveEnable");
                int changeType =rs.getInt("changeType");//1-节假日、2-工作日、3-休息日
                double value = rs.getDouble("val")<0?0:rs.getDouble("val");
                if(uintType==3 || uintType== 5 || uintType== 6){//按小时计算
                    value = Util.getDoubleValue(KQDurationCalculatorUtil.getDurationRound(value+""));
                }else{//按天计算
                    value = Util.getDoubleValue(KQDurationCalculatorUtil.getDurationRound(value+""));
                }
                String flowType = "";
                if(changeType==1){
                    flowType = "holidayOvertime";
                }else if(changeType==2){
                    flowType = "workingDayOvertime";
                }else if(changeType==3){
                    flowType = "restDayOvertime";
                }
                if("1".equalsIgnoreCase(paidLeaveEnable)){
                    //1表示关联调休
                    flowType += "_4leave";
                }else{
                    //0表示不关联调休
                    flowType += "_nonleave";
                }
                //df.format 默认是不四舍五入的 0.125这样的就会直接变成0.12了
                symbols.setDecimalSeparator('.');
                df.setMaximumFractionDigits(5);
                df.setDecimalFormatSymbols(symbols);
                datas.put(resourceid+"|"+belongdate+"|"+flowType, df.format(value));
            }
        }catch (Exception e){
            bb.writeLog("getDailyFlowOverTimeDataAllowance error:" + e.getMessage());
        }
        return datas;
    }
}
